const dayjs = require('dayjs');
const configs = require('../environments/configs');

(configs.mysql || []).forEach(item => item.type = 'mysql');
(configs.mssql || []).forEach(item => { item.type = 'mssql'; item.ip = item.Server; });

const dbItems = [];

if (configs.mysql) {
    dbItems.push(...configs.mysql);
}

if (configs.mssql) {
    dbItems.push(...configs.mssql);
}

if ((configs.env || {}).sqlite) {
    dbItems.push({ type: 'sqlite', name: 'inner-sqlite', display: '内置数据库(SQLite)' });
}

let index = 0;
dbItems.forEach(item => item.dbIndex = index++);

function getDbConfig (dbIndex = 0) {
    let setting = null;
    let index = parseInt(dbIndex);

    if (!isNaN(index)) {
        setting = dbItems[index]
    } else {
        setting = dbItems.find(d => d.name.toLowerCase() == (dbIndex || '').toLowerCase());
    }

    return setting;
}

module.exports = {
    dbs: dbItems,
    env: configs.env,
    getDbConfig: getDbConfig,
    httpClient: require('./exts/HttpClientHelper'),
    getResponse (message = '') {
        let rs = {
            at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
            success: true
        };

        if (message) {
            rs.success = false;

            if (typeof message == 'string') {
                rs.message = message;
            } else if (message.message) {
                rs.message = message.message;
            }
            else {
                try {
                    rs.message = JSON.stringify(message);
                } catch {
                    console.log(message)
                }
            }
        }

        return rs;
    }
};

/**
 * 显示固定位数的数字。
 * @param {Number} bits 固定的位数
 * @param {String} padChar 位数不足补充的字符
 * @returns {String} 固定位数的数字。 
 */
Number.prototype.leftPad = function (bits, padChar) {
    padChar = padChar || '0';

    var bitsArray = [padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar, padChar];
    var length = this.toFixed(0).toString().length;

    return (length >= bits) ? this : bitsArray.slice(0, bits - length).join('') + this;
};

/**
 * 日期格式化扩展。
 * @param {String} str 格式化字符串
 * @returns {String} 格式化后的字符串。
 */
Date.prototype.format = function (str) {
    return dayjs(this).format('YYYY-MM-DD HH:mm:ss');
};

/**
 * 字符格式的日期格式化。
 * @param {String} str 格式化字符串
 * @returns {String} 格式化后的字符串。
 */
String.prototype.dateFormat = function (str) {
    str = str || 'yyyy-MM-dd';
    var date = this.replace(/[年-]/, '/').replace(/[月-]/, '/').replace(/[日-]/, '/').replace(/(\/\s*)$/g, '');
    var items = date.split('/');
    var formats = str.split('-');

    if (items.length == 2) {
        return (parseInt(items[0]).leftPad(formats[0].length)) + '-' + parseInt(items[1].replace(/\s*/g, '')).leftPad(formats[1].length);
    } else if (items.length > 2) {
        return (new Date(parseInt(items[0]), parseInt(items[1]) - 1, parseInt(items[2]))).format(str);
    } else {
        return this;
    }
};

/**
 * 对象比较。
 * @param {Object} target 被比较的对象
 * @param {Array<String>} ignores 忽略的对象属性列表
 * @returns {Boolean} 是否相等
 */
Object.prototype.compare = function (target, ignores) {
    let sourceProps = Object.getOwnPropertyNames(this);
    let targetProps = Object.getOwnPropertyNames(target);

    if (sourceProps.length != targetProps.length) {
        return false;
    }

    for (let index = 0; index < sourceProps.length; index++) {
        let propName = sourceProps[index];

        if (ignores && ignores.find(i => i.toLowerCase() == propName.toLowerCase())) {
            continue;
        }

        if (typeof this[propName] != 'string' && this[propName] != target[propName]) {
            return false;
        } else if (typeof this[propName] != "string" && this[propName] == target[propName]) {
            continue;
        } else if ((this[propName] || "").toLowerCase() != (target[propName] || "").toLowerCase()) {
            return false;
        }
    }

    return true;
}

/**
 * 获取不在数组中的数据。
 * @param {Array} targets 目标数组。
 * @param {Array<String>} ignores 忽略比较的属性。
 * @returns {Array} 不包含在源数组中的元素。
 */
Array.prototype.getNotIncludes = function (targets, ignores) {
    if (typeof (this[0]) !== 'object') {
        return null;
    }

    if (!Array.isArray(targets)) {
        return null;
    }

    if (targets.length == 0) {
        return this;
    }

    let self = this;
    let notIncludes = [];

    self.forEach(function (t) {
        if (!targets.find(s => s.compare(t, ignores))) {
            notIncludes.push(t);
        }
    });

    return notIncludes;
}